package com.michaelbulava.TFS.vc.tfsitem;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.michaelbulava.TFS.common.item.ServerItemPath;
import com.microsoft.tfs.core.clients.versioncontrol.exceptions.ServerPathFormatException;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.ExtendedItem;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.PendingChange;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.RecursionType;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.Workspace;
import com.microsoft.tfs.core.clients.versioncontrol.specs.ItemSpec;
import com.microsoft.tfs.core.util.FileEncoding;

import java.io.File;
import java.text.MessageFormat;


/**
 * Created by MichaelA on 7/22/2015.
 */
public class TFSItem implements PathElement {
    private int remoteVersion;
    private final ServerItemPath path;
    private FileEncoding encoding;
    private ExtendedItem extendedItem;
    private boolean mappedLocalPathCalculated = false;
    private String mappedLocalPath;
    private final Workspace workspace;
    //protected final Project myProject;

//    public TFSItem(ServerItemPath path) {
//        this(path, null);
//    }

    public TFSItem(ServerItemPath path, Workspace workspace){//, Project project) {
        this.path = path;
        this.workspace = workspace;
        //this.myProject = project;
    }

//    public TFSItem(ExtendedItem extendedItem) {
//        this(extendedItem, null);
//    }

    public TFSItem(ExtendedItem extendedItem, Workspace workspace){//, Project project) {
        remoteVersion = extendedItem.getLatestVersion();
        path = new ServerItemPath(extendedItem.getTargetServerItem());
        encoding = extendedItem.getEncoding();

        this.extendedItem = extendedItem;

        this.workspace = workspace;
        //this.myProject = project;
    }

    protected Workspace getWorkspace() {
        return this.workspace;
    }

    public int getDeletionID() {
        return extendedItem != null ? extendedItem.getDeletionID() : 0;
    }

    public ItemSpec getItemSpec() {
        return new ItemSpec(getFullPath(), RecursionType.FULL, getDeletionID());
    }

    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof TFSItem)) {
            return false;
        }
        TFSItem other = (TFSItem)obj;
        return path.equals(other.path);
    }

    public int hashCode() {
        return path.hashCode();
    }

    public String toString() {
        String messageFormat = "TFSItem [{0}] ({1})";
        return MessageFormat.format("TFSItem [{0}] ({1})", new Object[] { path.getFullPath(), Integer.toHexString(System.identityHashCode(this)) });
    }

//    public boolean isLocal() {
//        if (getExtendedItem() == null) {
//            return true;
//        }
//        int localVersion = getLocalVersion();
//        if (localVersion > 0) {
//            return true;
//        }
//
//        VirtualFile myFile = LocalFileSystem.getInstance().findFileByIoFile(new File(this.getLocalPath()));
//        ChangeListManager changeListManager = ChangeListManager.getInstance(this.myProject);
//        if (changeListManager.getChange(myFile).getFileStatus() == FileStatus.ADDED)
//            return true;
////        PendingChange[] pendingChanges = getPendingChanges(false);
////        for (int i = 0; i < pendingChanges.length; i++) {
////            ChangeType changeType = pendingChanges[i].getChangeType();
////            if ((changeType.contains(ChangeType.ADD)) || (changeType.contains(ChangeType.BRANCH))) {
////                return true;
////            }
////        }
//        return false;
//    }

    public boolean isLatest() {
        return getLocalVersion() == remoteVersion;
    }

    public int getLocalVersion() {
        if ((extendedItem == null) || (extendedItem.getLocalItem() == null)) {
            return 0;
        }
        return extendedItem.getLocalVersion();
    }

    public String getName() {
        return path.getName();
    }

    public int getRemoteVersion() {
        return remoteVersion;
    }

    public String getFullPath() {
        return path.getFullPath();
    }

    public String getLocalPath() {
        if (extendedItem == null) {
            return workspace.getMappedLocalPath(path.getFullPath());
        }
        return extendedItem.getLocalItem();
    }

    public String getPath() {
        if ((getLocalPath() == null) || (!getLocalPath().equals(getMappedLocalPath()))) {
            return path.getFullPath();
        }
        return getLocalPath();
    }

    public String getSourceServerPath() {
        if ((getExtendedItem() == null) || (getExtendedItem().getSourceServerItem() == null)) {
            return path.getFullPath();
        }
        return getExtendedItem().getSourceServerItem();
    }

    public String getParentFullPath() {
        if (path.getParent() != null) {
            return path.getParent().getFullPath();
        }
        return null;
    }

    public ServerItemPath getItemPath() {
        return path;
    }

    public FileEncoding getEncoding() {
        return encoding;
    }

    public ExtendedItem getExtendedItem() {
        return extendedItem;
    }

    public boolean changeApplies(PendingChange change) {
        ServerItemPath serverItem = new ServerItemPath(change.getServerItem());
        if (serverItem.equals(getItemPath())) {
            return true;
        }
        if (change.getSourceServerItem() != null) {
            ServerItemPath sourceServerItem = new ServerItemPath(change.getSourceServerItem());
            if (sourceServerItem.equals(getItemPath())) {
                return true;
            }
        }
        return false;
    }

    /*public boolean hasPendingChanges() {
        return hasPendingChanges(true);
    }*/

    /*public boolean hasPendingChanges(boolean recursive) {
        PendingChange[] changes = getPendingChanges(recursive);

        return (changes != null) && (changes.length > 0);
    }*/

    /*public PendingChange[] getPendingChanges() {
        return getPendingChanges(true);
    }*/

//    public PendingChange[] getPendingChanges(boolean recursive) {
//        String serverPath = getFullPath();
//        if (serverPath == null) {
//            return new PendingChange[0];
//        }
//
//        ChangeListManager changeListManager = ChangeListManager.getInstance(this.myProject);
//        Collection<Change> changes = changeListManager.getAllChanges();
//
//        PendingChangeCache pendingChangeCache = getRepository().getPendingChangeCache();
//        PendingChange[] changes;
//        if (recursive) {
//            changes = pendingChangeCache.getPendingChangesByServerPathRecursive(serverPath);
//        } else {
//            PendingChange pendingChange = pendingChangeCache.getPendingChangeByServerPath(serverPath);
//
//            changes = pendingChange != null ? new PendingChange[] { pendingChange } : new PendingChange[0];
//        }
//        return changes;
//    }

    public boolean isDeleted() {
        return getItemSpec().getDeletionID() > 0;
    }

    public String getMappedLocalPath() {
        if (!mappedLocalPathCalculated) {
            try {
                mappedLocalPath = workspace.getMappedLocalPath(path.getFullPath());
            } catch (ServerPathFormatException e) {}
            mappedLocalPathCalculated = true;
        }
        return mappedLocalPath;
    }

//    public Project getProject(){
//        return this.myProject;
//    }


}
